<?php

namespace App\Services\Applet\Payment;

use App\Exceptions\PaymentException;
use App\Models\Applet\Other\PaymentOrderModel;
use App\Services\Applet\BaseAppletService;
use App\Services\Applet\Order\ShopOrderService;
use App\Services\Applet\Order\SponsorOrderService;
use Exception;

class BasePaymentService extends BaseAppletService
{

    // 支付类型
    const PAY_TYPE_WECHAT = 10;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 微信
    const PAY_TYPE_ALIPAY = 20;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // 支付宝

    const PAY_TYPE_LIST = [
        self::PAY_TYPE_WECHAT,
        self::PAY_TYPE_ALIPAY,
    ];

    // 应用平台
    const PLATFORM_APP    = 10;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // app
    const PLATFORM_APPLET = 20;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // 小程序
    const PLATFORM_H5     = 30;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // h5

    const PLATFORM_LIST = [
        self::PLATFORM_APP,
        self::PLATFORM_APPLET,
        self::PLATFORM_H5,
    ];

    const ORDER_TYPE_TITLE = [
        PaymentOrderModel::ORDER_TYPE_SPONSOR => '认养订单',
        PaymentOrderModel::ORDER_TYPE_SHOP => '商品订单'
    ];

    /**
     * 获取订单服务类
     *
     * @param int $orderType
     * @return SponsorOrderService|ShopOrderService
     * @throws PaymentException
     * @throws Exception
     */
    protected function getOrderService(int $orderType)
    {
        switch ($orderType) {
            case PaymentOrderModel::ORDER_TYPE_SPONSOR:
                return loadService('Applet\Order\SponsorOrderService');
            case PaymentOrderModel::ORDER_TYPE_SHOP:
                return loadService('Applet\Order\ShopOrderService');
            default:
                throw new PaymentException('订单类型错误', PaymentException::CODE_1001);
        }
    }

    /**
     * 支付
     *
     * @param string $orderNo 订单号
     * @param int $commission
     * @param int $payType 支付方式 10 微信 20 支付宝
     * @param int $platform 平台类型 10 app 20 小程序 30 h5
     * @param int $orderType 业务订单类型
     * @param array $params 额外参数
     * @return array
     * @throws PaymentException
     * @throws Exception
     */
    protected function getPaymentParams(string $orderNo, int $commission, int $payType, int $platform, int $orderType, array $params = []): array
    {
        $payService = $this->getPayService($payType);
        switch ($platform) {
            case self::PLATFORM_APP:
                throw new PaymentException('暂不支持此平台支付方式', PaymentException::CODE_1003);
            case self::PLATFORM_APPLET: // 小程序
                return $payService->appletPay(self::ORDER_TYPE_TITLE[$orderType], $orderNo, $commission, $params);
            case self::PLATFORM_H5: // h5
                return $payService->jsApiPay(self::ORDER_TYPE_TITLE[$orderType], $orderNo, $commission, $params);
            default:
                throw new PaymentException('暂不支持此平台支付方式', PaymentException::CODE_1003);
        }
    }

    /**
     * @param int $payType
     * @return AlipayService|WechatPayService
     * @throws PaymentException
     * @throws Exception
     */
    public function getPayService(int $payType)
    {
        switch ($payType) {
            case self::PAY_TYPE_WECHAT:
                return $this->newWechatPayService();
            case self::PAY_TYPE_ALIPAY:
                return $this->newAlipayService();
            default:
                throw new PaymentException('暂不支持此支付方式', PaymentException::CODE_1001);
        }
    }

    /**
     * @return WechatPayService
     * @throws Exception
     */
    public function newWechatPayService(): WechatPayService
    {
        return loadService('Applet\Payment\WechatPayService');
    }

    /**
     * @return AlipayService
     * @throws Exception
     */
    public function newAlipayService(): AlipayService
    {
        return loadService('Applet\Payment\AlipayService');
    }
}
